_text.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import re
  2. from ._functools import method_cache
  3. # from jaraco.text 3.5
  4. class FoldedCase(str):
  5. """
  6. A case insensitive string class; behaves just like str
  7. except compares equal when the only variation is case.
  8. >>> s = FoldedCase('hello world')
  9. >>> s == 'Hello World'
  10. True
  11. >>> 'Hello World' == s
  12. True
  13. >>> s != 'Hello World'
  14. False
  15. >>> s.index('O')
  16. 4
  17. >>> s.split('O')
  18. ['hell', ' w', 'rld']
  19. >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta']))
  20. ['alpha', 'Beta', 'GAMMA']
  21. Sequence membership is straightforward.
  22. >>> "Hello World" in [s]
  23. True
  24. >>> s in ["Hello World"]
  25. True
  26. You may test for set inclusion, but candidate and elements
  27. must both be folded.
  28. >>> FoldedCase("Hello World") in {s}
  29. True
  30. >>> s in {FoldedCase("Hello World")}
  31. True
  32. String inclusion works as long as the FoldedCase object
  33. is on the right.
  34. >>> "hello" in FoldedCase("Hello World")
  35. True
  36. But not if the FoldedCase object is on the left:
  37. >>> FoldedCase('hello') in 'Hello World'
  38. False
  39. In that case, use in_:
  40. >>> FoldedCase('hello').in_('Hello World')
  41. True
  42. >>> FoldedCase('hello') > FoldedCase('Hello')
  43. False
  44. """
  45. def __lt__(self, other):
  46. return self.lower() < other.lower()
  47. def __gt__(self, other):
  48. return self.lower() > other.lower()
  49. def __eq__(self, other):
  50. return self.lower() == other.lower()
  51. def __ne__(self, other):
  52. return self.lower() != other.lower()
  53. def __hash__(self):
  54. return hash(self.lower())
  55. def __contains__(self, other):
  56. return super().lower().__contains__(other.lower())
  57. def in_(self, other):
  58. "Does self appear in other?"
  59. return self in FoldedCase(other)
  60. # cache lower since it's likely to be called frequently.
  61. @method_cache
  62. def lower(self):
  63. return super().lower()
  64. def index(self, sub):
  65. return self.lower().index(sub.lower())
  66. def split(self, splitter=' ', maxsplit=0):
  67. pattern = re.compile(re.escape(splitter), re.I)
  68. return pattern.split(self, maxsplit)